package com.lz.service.smsmail.control;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.lz.cache.Cache;
import com.lz.cache.CacheFactory;
import com.lz.common.util.StringUtils;
import com.lz.service.common.generic.BaseControl;
import com.lz.service.common.response.CommonServiceResponseEnum;
import com.lz.service.common.response.ResponseBody;
import com.lz.service.common.smsmail.param.SmsMailServiceJuHeSmsSendParam;
import com.lz.service.common.smsmail.param.SmsMailServiceMailSendParam;
import com.lz.service.common.smsmail.response.SmsMailServiceResponseEnum;
import com.lz.service.smsmail.common.Config;
import com.lz.service.smsmail.juhe.JuHeSms;
import com.lz.service.smsmail.juhe.JuHeSmsResult;
import com.lz.service.smsmail.mail.MailSenderInfo;
import com.lz.service.smsmail.mail.SimpleMailSender;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping(value = "/api/v1", produces = "application/json;charset=UTF-8")
public class SmsMailControlV1 extends BaseControl{

	private static final Cache REDIS_CACHE = CacheFactory.getRedisCached();
	@Autowired
	private JuHeSms juHeSms;
	
	/**
	 * 聚合短信发送
	 * @param juHeSmsSendParam
	 * @return
	 */
	@ApiOperation(value = "聚合短信发送", notes = "聚合短信发送")
	@PostMapping("/sms/send")
	@HystrixCommand(fallbackMethod = "smsSendFallback")
	public Boolean smsSend(@RequestBody SmsMailServiceJuHeSmsSendParam juHeSmsSendParam) {
		String mobile = juHeSmsSendParam.getMobile();
		String tpl_id = juHeSmsSendParam.getTpl_id();
		String tpl_value = juHeSmsSendParam.getTpl_value();
		JuHeSmsResult juHeSmsResult = juHeSms.send(mobile, tpl_id, tpl_value);
        LOG.debug("error_code={}", juHeSmsResult.getError_code());
        if(juHeSmsResult.getError_code() == 0){
        	LOG.debug("result={}", juHeSmsResult.getResult());
        	return true;
        }else{
        	LOG.debug("reason={}", juHeSmsResult.getReason());
        	return false;
        }
	}
	
	/**
	 * 聚合短信发送，熔断处理
	 * @param juHeSmsSendParam
	 * @return
	 */
	public Boolean smsSendFallback(SmsMailServiceJuHeSmsSendParam juHeSmsSendParam) {
		LOG.info("===========into smsSendFallback===========");
		return false;
	}
	

	/**
	 * 邮件发送(文本)
	 * @param mailSendParam
	 * @return
	 */
	@ApiOperation(value = "邮件发送(文本)", notes = "邮件发送(文本)")
	@PostMapping("/mail/send")
	@HystrixCommand(fallbackMethod = "mailSendFallback")
	public Boolean mailSend(@RequestBody SmsMailServiceMailSendParam mailSendParam) {
		try {
			String toAddress = mailSendParam.getToAddress();
			String subject = mailSendParam.getSubject();
			String content = mailSendParam.getContent();
			MailSenderInfo mailInfo = new MailSenderInfo(Config.MAILSERVER_HOST, Config.MAILSERVER_PORT, 
					Config.MAIL_USERNAME, Config.MAIL_PASSWORD, 
					Config.MAIL_FROMADDRESS, toAddress,
					subject, content);
			SimpleMailSender sms = new SimpleMailSender();
			if(sms.sendTextMail(mailInfo)){
				LOG.debug("toAddress={} subject={} 邮件发送成功", toAddress, subject);
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	
	/**
	 * 邮件发送熔断处理
	 * @param mailSendParam
	 * @return
	 */
	public Boolean mailSendFallback(SmsMailServiceMailSendParam mailSendParam) {
		LOG.info("===========into mailSendFallback===========");
		return false;
	}
	
	/**
	 * 邮件发送(Html)
	 * @param mailSendParam
	 * @return
	 */
	@ApiOperation(value = "邮件发送(Html)", notes = "邮件发送(Html)")
	@PostMapping("/mail/sendHtml")
	@HystrixCommand(fallbackMethod = "mailSendHtmlFallback")
	public Boolean mailSendHtml(@RequestBody SmsMailServiceMailSendParam mailSendParam) {
		try {
			String toAddress = mailSendParam.getToAddress();
			String subject = mailSendParam.getSubject();
			String content = mailSendParam.getContent();
			MailSenderInfo mailInfo = new MailSenderInfo(Config.MAILSERVER_HOST, Config.MAILSERVER_PORT, 
					Config.MAIL_USERNAME, Config.MAIL_PASSWORD, 
					Config.MAIL_FROMADDRESS, toAddress,
					subject, content);
			SimpleMailSender sms = new SimpleMailSender();
			if(sms.sendHtmlMail(mailInfo)){
				LOG.debug("toAddress={} subject={} 邮件发送成功", toAddress, subject);
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	/**
	 * 邮件发送熔断处理
	 * @param mailSendParam
	 * @return
	 */
	public Boolean mailSendHtmlFallback(SmsMailServiceMailSendParam mailSendParam) {
		LOG.info("===========into mailSendHtmlFallback===========");
		return false;
	}
	/**
	 * 发送短信验证码，有进行短信验证码发送逻辑控制
	 * @param juHeSmsSendParam
	 * @return
	 */
	@ApiOperation(value="发送短信验证码", notes="发送短信验证码")
	@PostMapping("/sms/sendAuthcode")
	public ResponseBody sendAuthcode(@RequestBody SmsMailServiceJuHeSmsSendParam juHeSmsSendParam) {
		ResponseBody responseBody = null;
		if(!StringUtils.isNotBlank(juHeSmsSendParam.getTpl_id())){
			juHeSmsSendParam.setTpl_id(Config.JUHESMS_TPL_ID);
		}
		if(!StringUtils.isNotBlank(juHeSmsSendParam.getTpl_value())){
			juHeSmsSendParam.setTpl_value(Config.JUHESMS_TPL_VALUE);
		}
		Map<String, Object> resultMap = sendSmsByJuhe(juHeSmsSendParam);
		int result_code = (int) resultMap.get("code");
		if (result_code == 1) {
			responseBody = new ResponseBody(CommonServiceResponseEnum.IS_SUCCESS);
		} else {
			String message = (String) resultMap.get("message");
			responseBody = new ResponseBody(SmsMailServiceResponseEnum.SMS_SEND_ERROR, message, true);
		}
		return responseBody;
	}
	
	/**
	 * 根据手机号码获取验证码，如果没有则返回空串
	 * 如果用户输入的验证码同缓存中的验证码一致，则需要删掉缓存中的验证码
	 * @return
	 */
	@ApiOperation(value="根据手机号码获取验证码", notes="根据手机号码获取验证码")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "mobile_phone", value = "手机号码", required = true, dataType = "String",paramType = "path"),
		@ApiImplicitParam(name = "user_auth_code", value = "用户输入的验证码", required = true, dataType = "String",paramType = "path")
	})
	@GetMapping("/sms/getAuthcode/{mobile_phone}/{user_auth_code}")
	public String getAuthcode(@PathVariable String mobile_phone, @PathVariable String user_auth_code) {
		String cache_auth_code = getAuthCodeFromCache(mobile_phone, user_auth_code);
		String result = cache_auth_code==null?"":cache_auth_code; 
		LOG.info("getAuthcode mobile={} result={}", mobile_phone, result);
		return result;
	}
	
	/**
	 * 短信验证码发送逻辑控制
	 * @param juHeSmsSendParam
	 * @return
	 */
	public Map<String, Object> sendSmsByJuhe(SmsMailServiceJuHeSmsSendParam juHeSmsSendParam) {
		String phone = juHeSmsSendParam.getMobile();
		Map<String, Object> resultMap = new HashMap<String, Object>();
		String key_30s = "JuheSms_30_" + phone;
		String key_day = "JuheSms_day_" + phone;
		int v_30s = 0;
		int v_day = 0;
		if (REDIS_CACHE.get(key_30s) != null) {
			v_30s = Integer.parseInt(REDIS_CACHE.get(key_30s).toString());
		}
		if (REDIS_CACHE.get(key_day) != null) {
			v_day = Integer.parseInt(REDIS_CACHE.get(key_day).toString());
		}
		if (v_30s <= 3 && v_day <= 20) {
			int code = 0;
			Random r = new Random();
			while (true) {
				code = r.nextInt(999999);
				if (code > 99999) {
					break;
				}
			}
			String code_key = Config.SMS_AUTH_CODE_KEY + phone;
			LOG.info("code_key={} code={}", code_key, code);
			REDIS_CACHE.put(code_key, code, Config.SMS_AUTH_CODE_TIME);
			JuHeSmsResult juHeSmsResult = juHeSms.send(phone, juHeSmsSendParam.getTpl_id(), juHeSmsSendParam.getTpl_value().replace("111111", String.valueOf(code)));
			if(juHeSmsResult.getError_code() == 0){
				resultMap.put("code", 1);
				resultMap.put("message", "发送成功");
				v_30s++;
				v_day++;
				REDIS_CACHE.put(key_30s, v_30s, 1800);
				REDIS_CACHE.put(key_day, v_day, getTodaySurplusTime());
			} else {
				resultMap.put("code", -1);
				resultMap.put("message", "发送失败");
			}
		} else {
			resultMap.put("code", -1);
			resultMap.put("message", "操作频繁，请休息一下！");
		}
		return resultMap;
	}
	
	/**
	 * 获取短信验证码，并且当验证码正确的时候置为失效，防止二次使用
	 * @param mobile_phone 短信验证码的手机号
	 * @param user_auth_code 
	 * @return
	 */
	private String getAuthCodeFromCache(String mobile_phone, String user_auth_code) {
		String code_key = Config.SMS_AUTH_CODE_KEY + mobile_phone;
		LOG.debug("code_key={}", code_key);
		String authCode = (String) REDIS_CACHE.get(code_key);
		if(authCode != null && authCode.equals(user_auth_code)){
			REDIS_CACHE.delete(code_key);
		}
		return authCode;
	}
	
	
	/**
	 * 获取今日剩余时间秒数
	 * @return
	 */
	private static Integer getTodaySurplusTime() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.add(Calendar.DAY_OF_MONTH, 1);
		Date now = new Date();
		long interval = (cal.getTimeInMillis() - now.getTime()) / 1000;
		return (int) interval;
	}
	
}
